package org.chimi.rr4s.application;

import java.util.Date;

import org.chimi.rr4s.domain.Action;
import org.chimi.rr4s.domain.Item;
import org.chimi.rr4s.domain.ItemRepository;
import org.chimi.rr4s.domain.User;
import org.chimi.rr4s.domain.UserRepository;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author Choi, Beom Kyun
 */
public class DomainAddActionService implements AddActionService {

	private UserRepository userRepository;
	private ItemRepository itemRepository;

	@Transactional
	@Override
	public void addViewedAction(String sessionId, String userId, String itemId,
			String itemType, Date time) {
		addAction(sessionId, userId, itemId, itemType, time, "VIEWED");
	}

	private void addAction(String sessionId, String userId, String itemId,
			String itemType, Date time, String actionType) {
		User user = getOrCreateUser(sessionId, userId);
		Item item = getOrCreateItem(itemId, itemType);
		relatedAction(user, item, time, actionType);
	}

	private Item getOrCreateItem(String itemId, String itemType) {
		Item item = itemRepository.findByPropertyValue("id", itemId);
		if (item != null) {
			return item;
		}
		return itemRepository.save(new Item(itemId, itemType));
	}

	private User getOrCreateUser(String sessionId, String userId) {
		if (userId != null) {
			return getOrCreateUserBySessionIdUserIdProperty(sessionId, userId,
					"id");
		}
		return getOrCreateUserBySessionIdUserIdProperty(sessionId, userId,
				"sessionId");
	}

	private void relatedAction(User user, Item item, Date time,
			String actionType) {
		Action action = user.relateTo(item, Action.class, actionType, true);
		action.setActionTime(time != null ? time : new Date());
	}

	private User getOrCreateUserBySessionIdUserIdProperty(String sessionId,
			String userId, String propertyName) {
		User user = userRepository.findByPropertyValue(propertyName, userId);
		if (user != null) {
			return user;
		}
		return userRepository.save(new User(sessionId, userId));
	}

	@Transactional
	@Override
	public void addBoughtAction(String sessionId, String userId, String itemId,
			String itemType, Date time) {
		addAction(sessionId, userId, itemId, itemType, time, "BOUGHT");
	}

	@Transactional
	@Override
	public void addLikedAction(String sessionId, String userId, String itemId,
			String itemType, Date time) {
		addAction(sessionId, userId, itemId, itemType, time, "LIKED");
	}

}
